Related inputs
There are chances that more than one <input> elements need to be held within one <ValidityWrapper> because it may be how the downstream component designed. For that, the API allows a model argument carries a HASH, with data structure of key-pair, where the key represents the name attribute of the associated <input> (or <select>) element.
<ValidatorContainer as |v|>
<v.validity
@validator={{this.customValidator}}
@model={{hash method=this.method value=this.value}}
as |validity|
>
<h3>Method:</h3>
<input
name="method"
type="radio"
value="email"
id="method-email"
required
{{on "input" this.onChangeMethod}}
checked={{eq this.method "email"}}
/>
<label for="method-email">e-mail</label>
<input
name="method"
type="radio"
value="url"
id="method-url"
required
{{on "input" this.onChangeMethod}}
checked={{eq this.method "url"}}
/>
<label for="method-url">URL</label>
{{#if validity.errorMessage.method}}
<p data-test-error>{{validity.errorMessage.method}}</p>
{{/if}}
<h3>Value:</h3>
<input
autocomplete="noop"
type={{this.method}}
name="value"
data-test-value
value={{this.value}}
required
{{on 'input' this.onChangeValue}}
/>
{{#if validity.errorMessage.value}}
<p data-test-error>{{validity.errorMessage.value}}</p>
{{/if}}
</v.validity>
<p>
<button disabled={{not v.isValid}} {{on 'click' (fn v.checkForm this.onSubmit)}}>
save
</button>
</p>
</ValidatorContainer>
In this example, the form consists of 2 fields-- method and value, to represent a communication channel. However, we have done a couple of things to make it work:
- employ
methodandvalueas the key in themodelobject passed intov.validity - decorate
nameattribute of input fields, usingmethodandvalue - In order to convey the error state separately, the
validity.errorMessageholds error message for both of them with the same key pair
Underneath, the library uses the name to locate the corresponding DOM element to collect constraint validation error or set custom error perceived from custom validator
The example dynamically update type attribute of input with name="value" in order to leverage the constraint validation result from browser. We also created a custom validation in case any specific business logic is involved.
@action
customValidator({ value, method }) {
return {
value: /invalid/.test(value)
? 'CUSTOM_VALIDATION_ERROR1'
: method === 'url' && /\.com/.test(value)
? ''
: 'CUSTOM_VALIDATION_ERROR2',
method: '',
};
}
The custom validator is expecting model to be passed, implementing to rules:
- For any method kind, the value cannot include keyword of
invalid - When the
methodisurl, it needs to include the keyword of.com